package com.render.game;

import java.util.ArrayList;
import java.util.HashMap;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Matrix4;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Disposable;
import com.engine.game.Event;
import com.engine.game.GameEntity;


public class Renderer implements Disposable{
	
	private ArrayList<Event> events;
	
	
	private PhysicsCamera camera;
	private Matrix4 matrix;
	
	private ArrayList<Stage> listOfStages;
	
	private SpriteBatch batch;
	
	private Vector2 currentWindowMax;
	
	
	
	public Renderer(Vector2 worldMax, Vector2 screenMax){
		batch = new SpriteBatch();
		matrix = new Matrix4();
		
		camera = new PhysicsCamera(worldMax, screenMax);
		
		this.currentWindowMax = new Vector2(screenMax);
		
		
		events = new ArrayList<Event>();
		listOfStages = new ArrayList<Stage>();
		
		updateMatrix();
	}
	
	public void changeScreenMinInWorld(Vector2 v){
		camera.screenMinInWorld.set(v);
	}
	
    public void changeScreenMaxInWorld(Vector2 v){
		camera.screenMaxInWorld.set(v);
	}
    
    public Vector2 getWorldCoordinates(Vector2 v){
		return new Vector2(this.camera.screenToWorld(v));
    }
    
	
	public void resize(int width, int height){
		
		
		camera.reshape(0, 0, width, height);
		
		
		
		
		for(Stage s : this.listOfStages){
		
			float fx = (width/this.currentWindowMax.x);
			float fy = (height/this.currentWindowMax.y);
			
			
					
			s.changeViewport(new Vector2((fx * s.getViewportMin().x), (fy * s.getViewportMin().y)), 
					new Vector2((fx * s.getViewportMax().x), (fy * s.getViewportMax().y)));
		}
		
		this.currentWindowMax = new Vector2(width, height);
		
	}
	
	public void updateMatrix(){
		matrix.setToOrtho(camera.screenMinInWorld.x, camera.screenMaxInWorld.x,
				camera.screenMinInWorld.y, camera.screenMaxInWorld.y, -1.0f, 1.0f);
	}
	
	
	
	
	public void render(HashMap<String, GameEntity> mapOfGameObjects, float alpha){
		
		Gdx.gl.glClearColor(0, 0, 0, 1);
		Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
		
		batch.begin();
		
		for(Stage s : listOfStages){
			
			changeScreenMinInWorld(s.getScreenMinInWorld());
			changeScreenMaxInWorld(s.getScreenMaxInWorld());
			
			updateMatrix();
			
			batch.setProjectionMatrix(matrix);
			
			s.render(mapOfGameObjects, batch, alpha);
			
			batch.flush();
		}
		
		batch.end();
	}
	
	public void receiveMessage(Event event){
		events.add(event);
	}
	
	public void clearEvents(){
		events.clear();
	}
	
	public void update(){
		for(Event e : events){
			if(e.getMessage().contains("pan")){
				String[] parts = e.getMessage().split(";");
				if(parts.length == 3){
					listOfStages.get(0).pan(new Vector2(Integer.parseInt(parts[1]), Integer.parseInt(parts[2])));
				}
				else{
					listOfStages.get(Integer.parseInt(parts[3])).pan(new Vector2(Integer.parseInt(parts[1]), Integer.parseInt(parts[2])));
				}
				
			}
			else if(e.getMessage().contains("zoom")){
				String[] parts = e.getMessage().split(";");
				if(parts.length == 3){
					listOfStages.get(0).zoom(new Vector2(Integer.parseInt(parts[1]), Integer.parseInt(parts[2])));
				}
				else{
					listOfStages.get(Integer.parseInt(parts[3])).zoom(new Vector2(Integer.parseInt(parts[1]), Integer.parseInt(parts[2])));
				}
			}

		}
		
		clearEvents();
	}
	
	public void addStage(Stage stage){
		this.listOfStages.add(stage);
	}
	
	
	public void clearStages(){
		this.listOfStages.clear();
	}
	
	public void clearStage(int index){
		this.listOfStages.remove(index);
	}
	
	public Stage getStage(int index){
		return this.listOfStages.get(index);
	}
	
	public void pushObjectToStage(String name, RenderType type, int index, int stage){
		listOfStages.get(stage).pushObject(name, type, index);
	}
	
	public void pushObjectToStage(String name, RenderType type, int stage){
		listOfStages.get(stage).pushObject(name, type);
	}
	
	public void deleteObjectFromStage(String name, RenderType type, int stage){
		listOfStages.get(stage).deleteObject(name, type);
	}

	@Override
	public void dispose() {
		
		clearEvents();
		clearStages();
		batch.dispose();
		
	}
	
	

}
